import os
import tkinter as tk
from tkinter import filedialog, messagebox
import re

def select_video_directory():
    """选择视频目录"""
    root = tk.Tk()
    root.withdraw()
    root.attributes("-topmost", True)
    
    video_dir = filedialog.askdirectory(
        title="选择视频文件目录",
        mustexist=True
    )
    root.destroy()
    return video_dir

def select_markdown_directory():
    """选择Markdown笔记目录"""
    root = tk.Tk()
    root.withdraw()
    root.attributes("-topmost", True)
    
    md_dir = filedialog.askdirectory(
        title="选择Markdown笔记目录",
        mustexist=True
    )
    root.destroy()
    return md_dir

def get_all_video_files(video_dir):
    """递归获取所有视频文件"""
    video_extensions = {
        '.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm', 
        '.m4v', '.mpg', '.mpeg', '.3gp', '.ts', '.mts', '.m2ts',
        '.rmvb', '.rm', '.asf', '.vob', '.dat', '.m2v', '.divx'
    }
    
    video_files = []
    for root, dirs, files in os.walk(video_dir):
        for file in files:
            file_ext = os.path.splitext(file)[1].lower()
            if file_ext in video_extensions:
                full_path = os.path.join(root, file)
                relative_path = os.path.relpath(full_path, video_dir)
                video_files.append({
                    'full_path': full_path,
                    'relative_path': relative_path,
                    'filename': file,
                    'name_without_ext': os.path.splitext(file)[0]
                })
    
    return video_files

def get_all_markdown_files(md_dir):
    """递归获取所有Markdown文件"""
    md_files = []
    for root, dirs, files in os.walk(md_dir):
        for file in files:
            if file.lower().endswith(('.md', '.markdown')):
                full_path = os.path.join(root, file)
                relative_path = os.path.relpath(full_path, md_dir)
                md_files.append({
                    'full_path': full_path,
                    'relative_path': relative_path,
                    'filename': file,
                    'name_without_ext': os.path.splitext(file)[0]
                })
    
    return md_files

def extract_video_references_from_md(md_file_path):
    """从Markdown文件中提取视频引用链接"""
    video_references = set()
    
    try:
        with open(md_file_path, 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read()
        
        # 匹配各种可能的视频引用格式
        patterns = [
            # ![描述](视频文件路径)
            r'!\[.*?\]\((.*?\.(mp4|avi|mkv|mov|wmv|flv|webm|m4v|mpg|mpeg|3gp|ts|mts|m2ts|rmvb|rm|asf|vob|dat|m2v|divx))\)',
            # [描述](视频文件路径)
            r'\[.*?\]\((.*?\.(mp4|avi|mkv|mov|wmv|flv|webm|m4v|mpg|mpeg|3gp|ts|mts|m2ts|rmvb|rm|asf|vob|dat|m2v|divx))\)',
            # 直接的文件名引用
            r'[\s\"\']([^\"\'\s]+\.(mp4|avi|mkv|mov|wmv|flv|webm|m4v|mpg|mpeg|3gp|ts|mts|m2ts|rmvb|rm|asf|vob|dat|m2v|divx))[\s\"\']',
            # HTML视频标签
            r'<video[^>]*src=[\"\']([^\"\']+\.(mp4|avi|mkv|mov|wmv|flv|webm|m4v|mpg|mpeg|3gp|ts|mts|m2ts|rmvb|rm|asf|vob|dat|m2v|divx))[\"\'][^>]*>',
            # Wiki链接格式
            r'\[\[([^\]\n]+\.(mp4|avi|mkv|mov|wmv|flv|webm|m4v|mpg|mpeg|3gp|ts|mts|m2ts|rmvb|rm|asf|vob|dat|m2v|divx))\]\]'
        ]
        
        for pattern in patterns:
            matches = re.findall(pattern, content, re.IGNORECASE)
            for match in matches:
                if isinstance(match, tuple):
                    video_ref = match[0]  # 第一个元素是文件名
                else:
                    video_ref = match
                
                # 清理引用，只保留文件名
                video_filename = os.path.basename(video_ref)
                video_references.add(video_filename.lower())
                
    except Exception as e:
        print(f"读取文件 {md_file_path} 时出错: {e}")
    
    return video_references

def check_video_notes_coverage(video_files, md_files):
    """检查视频文件的笔记覆盖情况"""
    # 收集所有Markdown文件中的视频引用
    all_video_references = set()
    md_file_references = {}
    
    for md_file in md_files:
        references = extract_video_references_from_md(md_file['full_path'])
        all_video_references.update(references)
        md_file_references[md_file['full_path']] = references
    
    # 检查每个视频文件是否有对应的引用
    results = {
        'covered': [],      # 有笔记的视频
        'missing': [],      # 没有笔记的视频
        'statistics': {
            'total_videos': len(video_files),
            'covered_videos': 0,
            'missing_videos': 0,
            'coverage_rate': 0.0
        }
    }
    
    for video in video_files:
        video_filename_lower = video['filename'].lower()
        
        # 检查精确匹配
        if video_filename_lower in all_video_references:
            results['covered'].append(video)
            results['statistics']['covered_videos'] += 1
        else:
            # 检查文件名（无扩展名）匹配
            video_name_lower = video['name_without_ext'].lower()
            found_match = False
            
            for ref in all_video_references:
                ref_name_lower = os.path.splitext(ref)[0].lower()
                if video_name_lower == ref_name_lower:
                    found_match = True
                    break
            
            if found_match:
                results['covered'].append(video)
                results['statistics']['covered_videos'] += 1
            else:
                results['missing'].append(video)
                results['statistics']['missing_videos'] += 1
    
    # 计算覆盖率
    if results['statistics']['total_videos'] > 0:
        results['statistics']['coverage_rate'] = (
            results['statistics']['covered_videos'] / results['statistics']['total_videos'] * 100
        )
    
    return results, md_file_references

def generate_report(results, md_file_references, video_dir, md_dir):
    """生成检查报告"""
    report = []
    report.append("=" * 60)
    report.append("视频文件笔记覆盖检查报告")
    report.append("=" * 60)
    report.append(f"视频目录: {video_dir}")
    report.append(f"笔记目录: {md_dir}")
    report.append("")
    
    # 统计信息
    stats = results['statistics']
    report.append(f"统计信息:")
    report.append(f"  总视频文件数: {stats['total_videos']}")
    report.append(f"  已有笔记的视频: {stats['covered_videos']}")
    report.append(f"  缺失笔记的视频: {stats['missing_videos']}")
    report.append(f"  覆盖率: {stats['coverage_rate']:.1f}%")
    report.append("")
    
    # 缺失笔记的视频列表
    if results['missing']:
        report.append("缺失笔记的视频文件:")
        report.append("-" * 40)
        for i, video in enumerate(results['missing'], 1):
            report.append(f"{i:2d}. {video['relative_path']}")
        report.append("")
    
    # 已有笔记的视频列表
    if results['covered']:
        report.append("已有笔记的视频文件:")
        report.append("-" * 40)
        for i, video in enumerate(results['covered'], 1):
            report.append(f"{i:2d}. {video['relative_path']}")
        report.append("")
    
    # Markdown文件的引用情况
    report.append("Markdown文件引用统计:")
    report.append("-" * 40)
    for md_file, references in md_file_references.items():
        rel_path = os.path.relpath(md_file, md_dir)
        report.append(f"{rel_path}: {len(references)} 个视频引用")
    
    return "\n".join(report)

def save_report_to_file(report, default_filename="video_notes_check_report.txt"):
    """保存报告到文件"""
    root = tk.Tk()
    root.withdraw()
    
    file_path = filedialog.asksaveasfilename(
        title="保存检查报告",
        defaultextension=".txt",
        filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")],
        initialfile=default_filename
    )
    
    if file_path:
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(report)
            return file_path
        except Exception as e:
            messagebox.showerror("错误", f"保存报告失败: {e}")
            return None
    
    return None

def main():
    """主函数"""
    try:
        # 选择视频目录
        print("请选择视频文件目录...")
        video_dir = select_video_directory()
        if not video_dir:
            messagebox.showinfo("取消", "用户取消选择视频目录")
            return
        
        # 选择Markdown目录
        print("请选择Markdown笔记目录...")
        md_dir = select_markdown_directory()
        if not md_dir:
            messagebox.showinfo("取消", "用户取消选择笔记目录")
            return
        
        # 检查目录是否相同
        if os.path.abspath(video_dir) == os.path.abspath(md_dir):
            if not messagebox.askyesno("确认", "视频目录和笔记目录相同，是否继续？"):
                return
        
        # 扫描文件
        messagebox.showinfo("开始扫描", "开始扫描视频和笔记文件，这可能需要一些时间...")
        
        print("扫描视频文件...")
        video_files = get_all_video_files(video_dir)
        print(f"找到 {len(video_files)} 个视频文件")
        
        print("扫描Markdown文件...")
        md_files = get_all_markdown_files(md_dir)
        print(f"找到 {len(md_files)} 个Markdown文件")
        
        if not video_files:
            messagebox.showwarning("警告", "在视频目录中未找到任何视频文件")
            return
        
        # 检查覆盖情况
        print("检查笔记覆盖情况...")
        results, md_file_references = check_video_notes_coverage(video_files, md_files)
        
        # 生成报告
        report = generate_report(results, md_file_references, video_dir, md_dir)
        
        # 显示结果
        print("\n" + report)
        
        # 保存报告
        if messagebox.askyesno("保存报告", "是否保存检查报告到文件？"):
            saved_path = save_report_to_file(report)
            if saved_path:
                messagebox.showinfo("成功", f"报告已保存到: {saved_path}")
        
        # 显示摘要
        stats = results['statistics']
        summary = f"检查完成!\n\n总视频数: {stats['total_videos']}\n已有笔记: {stats['covered_videos']}\n缺失笔记: {stats['missing_videos']}\n覆盖率: {stats['coverage_rate']:.1f}%"
        
        if results['missing']:
            messagebox.showwarning("检查结果", summary + "\n\n存在缺失笔记的视频文件！")
        else:
            messagebox.showinfo("检查结果", summary + "\n\n所有视频都有对应的笔记！")
            
    except Exception as e:
        messagebox.showerror("错误", f"程序执行出错: {e}")
        print(f"错误: {e}")

if __name__ == "__main__":
    main()